﻿using LevelEditor.Model.Entity;
using LevelEditor.Model.Enum;
using LevelEditor.Model.IO;
using LevelEditor.Utils;
using LevelEditor.View.UserControls;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Markup;

namespace LevelEditor.View.Windows
{
    public partial class AssetsManagerWindow : Window
    {
        // Fields
        private OpenFileDialog addAssetDlg;

        // Methods
        public AssetsManagerWindow()
        {
            this.InitializeComponent();
            this.addAssetBtn.Click += new RoutedEventHandler(this.addAssetBtn_Click);
            this.removeAssetBtn.Click += new RoutedEventHandler(this.removeAssetBtn_Click);
            this.closeBtn.Click += new RoutedEventHandler(this.closeBtn_Click);
            this.assetsDG.SelectionChanged += new SelectionChangedEventHandler(this.assetsDG_SelectionChanged);
            this.gameSpriteEditor.GameSpriteChanged += new EventHandler(this.gameSpriteEditor_GameSpriteChanged);
            base.Closing += new CancelEventHandler(this.AssetsManagerWindow_Closing);
            this.LoadAssetsFromXml();
        }

        protected void addAssetBtn_Click(object sender, RoutedEventArgs e)
        {
            if (this.addAssetDlg == null)
            {
                this.addAssetDlg = new OpenFileDialog();
                this.addAssetDlg.AddExtension = true;
                this.addAssetDlg.Multiselect = true;
                this.addAssetDlg.Filter = "Image|*.png;*.jpeg;*.jpg";
                this.addAssetDlg.FileOk += new CancelEventHandler(this.addAssetDlg_FileOk);
            }
            this.addAssetDlg.ShowDialog();
        }

        protected void addAssetDlg_FileOk(object sender, CancelEventArgs e)
        {
            string appPath = FileUtil.AppStartUpPath;
            DirectoryInfo assetsSpritesDir = new DirectoryInfo(appPath + @"Assets\Sprites");
            if (!assetsSpritesDir.Exists)
            {
                assetsSpritesDir.Create();
            }
            Stream[] fileStreams = this.addAssetDlg.OpenFiles();
            string[] fileNames = this.addAssetDlg.SafeFileNames;
            for (int i = 0; i < fileStreams.Length; i++)
            {
                bool keepFile = false;
                bool isOverride = false;
                string filePath = appPath + @"Assets\Sprites\" + fileNames[i];
                FileInfo assetFile = new FileInfo(filePath);
                if (assetFile.Exists)
                {
                    switch (MessageBox.Show("The file '" + fileNames[i] + "' already exist!\n Do you want to replace it with the new one?", "", MessageBoxButton.YesNo, MessageBoxImage.Question))
                    {
                        case MessageBoxResult.Yes:
                            assetFile.Delete();
                            isOverride = true;
                            break;

                        case MessageBoxResult.No:
                            keepFile = true;
                            break;
                    }
                }
                if (!keepFile)
                {
                    using (FileStream fileStream = File.Create(filePath))
                    {
                        fileStreams[i].CopyTo(fileStream);
                    }
                    if (!isOverride)
                    {
                        string relativeUrl = filePath.Replace(appPath, @"\").Replace(@"\", "/");
                        GameSprite sprite = new GameSprite
                        {
                            ImageSource = new Uri(relativeUrl, UriKind.Relative),
                            Name = fileNames[i],
                            Category = "New!",
                            AssetType = AssetType.REGULAR_SPRITE
                        };
                        this.Assets.Add(sprite);
                    }
                }
            }
            this.SaveAll();
        }

        private void Assets_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (this.editTab.IsSelected)
            {
                this.gameSpriteEditor.GameSprite = this.assetsDG.SelectedItem as GameSprite;
            }
        }

        protected void assetsDG_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.assetsDG.SelectedItems.Count == 0)
            {
                this.viewTab.Visibility = Visibility.Collapsed;
                this.editTab.Visibility = Visibility.Collapsed;
                this.groupsTab.Visibility = Visibility.Collapsed;
            }
            else if (this.assetsDG.SelectedItems.Count == 1)
            {
                this.viewTab.Visibility = Visibility.Visible;
                this.editTab.Visibility = Visibility.Visible;
                this.groupsTab.Visibility = Visibility.Collapsed;
                this.editTab.IsSelected = true;
                this.gameSpriteEditor.GameSprite = this.assetsDG.SelectedItem as GameSprite;
            }
            else if (this.assetsDG.SelectedItems.Count > 1)
            {
                this.viewTab.Visibility = Visibility.Collapsed;
                this.editTab.Visibility = Visibility.Collapsed;
                this.groupsTab.Visibility = Visibility.Visible;
                this.groupsTab.IsSelected = true;
            }
        }

        protected void AssetsManagerWindow_Closing(object sender, CancelEventArgs e)
        {
            this.SaveAll();
        }

        protected void closeBtn_Click(object sender, RoutedEventArgs e)
        {
            base.Close();
        }

        protected void gameSpriteEditor_GameSpriteChanged(object sender, EventArgs e)
        {
            GameSprite gameSprite = sender as GameSprite;
            int indexGS = this.Assets.IndexOf(this.assetsDG.SelectedItem as GameSprite);
            this.Assets[indexGS] = gameSprite;
        }

        private void LoadAssetsFromXml()
        {
            this.Assets = new ObservableCollection<GameSprite>();
            this.Assets.CollectionChanged += new NotifyCollectionChangedEventHandler(this.Assets_CollectionChanged);
            List<GameSprite> gameSprites = GameSpritesIO.LoadGameSprites();
            for (int i = 0; i < gameSprites.Count; i++)
            {
                this.Assets.Add(gameSprites[i]);
            }
            ListCollectionView lcv = new ListCollectionView(this.Assets)
            {
                GroupDescriptions = { new PropertyGroupDescription("Category") }
            };
            this.assetsDG.ItemsSource = lcv;
        }

        protected void removeAssetBtn_Click(object sender, RoutedEventArgs e)
        {
            switch (MessageBox.Show("Are you sure you want to delete the selected sprite(s)?", "Warning", MessageBoxButton.YesNoCancel, MessageBoxImage.Exclamation))
            {
                case MessageBoxResult.Cancel:
                case MessageBoxResult.No:
                    return;
            }
            string appPath = FileUtil.AppStartUpPath;
            for (int i = this.assetsDG.SelectedItems.Count - 1; i >= 0; i--)
            {
                GameSprite gameSprite = this.assetsDG.SelectedItems[i] as GameSprite;
                FileInfo assetFile = new FileInfo(appPath + gameSprite.ImageSource.OriginalString);
                if (assetFile.Exists)
                {
                    assetFile.Delete();
                }
                this.Assets.Remove(this.assetsDG.SelectedItems[i] as GameSprite);
            }
            this.SaveAll();
        }

        private void SaveAll()
        {
            GameSpritesIO.SaveGameSprites(this.Assets.ToList<GameSprite>());
        }

        // Properties
        public ObservableCollection<GameSprite> Assets { get; set; }
    }
}
